const { Category, Course, User, Attachment, Chapter } = require("../../models");
const { Op } = require("sequelize");
const { NotFoundError } = require("../../utils/errors");
const { paging } = require("../../utils/utils");
const {
  deleteFileAttachmentByBusinessId,
} = require("../upload/attachmentService");

/**
 * 获取分页列表
 * @param req
 * @returns {Promise<{rows: Model[], count: number}>}
 */
exports.list = async (req) => {
  try {
    // 获取分页参数
    const { query, currentPage, pageSize, offset } = paging(req);
    // 排序+分页
    const condition = {
      ...getCondition(),
      order: [["id", "ASC"]],
      limit: pageSize,
      offset: offset,
    };
    // 查询条件
    queryCondition(query, condition);
    // 分页查询
    const { count, rows } = await Course.findAndCountAll(condition);
    return { rows, count, currentPage, pageSize };
  } catch (error) {
    throw new Error(error);
  }
};

/**
 * 获取详情
 * @param id
 * @returns {Promise<Model<*, TModelAttributes>>}
 */
exports.details = async (id) => {
  try {
    return await this.getById(id);
  } catch (error) {
    throw new Error(error);
  }
};

/**
 * 创建
 * @param body
 * @returns {Promise<Model<any, TModelAttributes>>}
 */
exports.create = async (body) => {
  try {
    return await Course.create(body);
  } catch (error) {
    throw new Error(error);
  }
};

/**
 * 删除
 * @param id
 * @returns {Promise<void>}
 */
exports.del = async (id) => {
  try {
    const course = await this.getById(id);
    const count = await Chapter.count({
      where: { courseId: id },
    });
    if (count > 0) {
      throw new Error(`当前课程有 ${count} 个章节，无法删除。`);
    }
    await deleteFileAttachmentByBusinessId(id);
    await course.destroy();
  } catch (error) {
    throw new Error(error);
  }
};

/**
 * 更新
 * @param id
 * @param body
 * @returns {Promise<Model<*, TModelAttributes>>}
 */
exports.update = async (id, body) => {
  try {
    const course = await this.getById(id);
    return course.update(body);
  } catch (error) {
    throw new Error(error);
  }
};

/**
 * 根据id获取
 * @param id
 * @returns {Promise<Model<any, TModelAttributes>>}
 */
exports.getById = async (id) => {
  // 获取当前
  const course = await Course.findByPk(id);
  if (!course) {
    throw new NotFoundError(`ID: ${id} not found`);
  }
  return course;
};

/**
 * 查询条件
 * @param query
 * @param condition
 */
function queryCondition(query, condition) {
  const { categoryId, userId, name, recommended, introductory, content } =
    query;
  if (name) {
    condition.where = {
      name: {
        [Op.like]: `%${name}%`,
      },
    };
  }
  if (recommended) {
    condition.where = {
      recommended: {
        [Op.eq]: recommended === "true",
      },
    };
  }
  if (introductory) {
    condition.where = {
      introductory: {
        [Op.eq]: introductory === "true",
      },
    };
  }
  if (content) {
    condition.where = {
      content: {
        [Op.like]: `%${content}%`,
      },
    };
  }
  if (categoryId) {
    condition.where = {
      categoryId: {
        [Op.eq]: categoryId,
      },
    };
  }
  if (userId) {
    condition.where = {
      userId: {
        [Op.eq]: userId,
      },
    };
  }
}

/**
 * 获取查询条件
 * @returns {{attributes: {exclude: string[]}, include: *[]}}
 */
function getCondition() {
  return {
    attributes: { exclude: ["CategoryId", "UserId"] },
    include: [
      {
        model: Category,
        as: "category", //别名
        attributes: ["id", "name"], // 查询限定 id name
      },
      {
        model: User,
        as: "user",
        attributes: ["id", "userName", "avatar"],
      },
      {
        model: Attachment,
        as: "attachmentList",
        attributes: ["filePath"],
      },
    ],
  };
}
